#ifndef REGIONMANAGER_H_INCLUDED
#define REGIONMANAGER_H_INCLUDED

#include <map>
#include <vector>

#include <wx/string.h>

using namespace std;

enum LangId
{
    SIMPLE_CHINESE = 1,
    TRADITIONAL_CHINESE,
    ENGLISH,
    REGION_CODE,
};

class RegionField
{
public:
    RegionField(int id = 0, int parentId = 0);
    inline wxString GetName(int langId) const {return HasLang(langId)?m_langName.find(langId)->second:wxT("");}
    inline void SetName(int langId, const wxString & name) {m_langName[langId] = name;}

    inline int GetParentId() const {return m_parentId;}
    inline void SetParentId(int parentId) {m_parentId = parentId;}

    inline int GetId() const {return m_id;}
    inline void SetId(int id) {m_id = id;}

    inline bool IsEmpty() const {return m_langName.empty() && m_childrenId.empty() && m_id == 0 && m_parentId == 0;}

    inline bool HasLang(int langId) const {return m_langName.find(langId) != m_langName.end();}

    bool MatchName(const wxString & name, bool wholeWord = false) const;

    bool MatchName(const RegionField & field) const;

    inline const vector<int> & GetChildrenId() const {return m_childrenId;}

    inline void AddChildId(int childId);

    wxString GetDumpData(int maxLangId);

    inline wxString GetLogName() const
    {
        return wxString::Format(wxT("(%s, %s, %s, %s)"),
            GetName(SIMPLE_CHINESE).c_str(), GetName(TRADITIONAL_CHINESE).c_str(),
            GetName(ENGLISH).c_str(), GetName(REGION_CODE).c_str());
    }

    static bool CmpId(const RegionField & a, const RegionField & b)
    {
        return a.m_id < b.m_id;
    }

private:
    int m_id = 0;
    int m_parentId = 0;
    map<int, wxString> m_langName;
    vector<int> m_childrenId;
};

class Region
{
public:
    inline const RegionField & GetCountry() const {return m_country;}
    inline RegionField * GetMutableCountry() {return &m_country;}
    inline void SetCountry(const RegionField & country) {m_country = country;}

    inline const RegionField & GetProvince() const {return m_province;}
    inline RegionField * GetMutableProvince() {return &m_province;}
    inline void SetProvince(const RegionField & province) {m_province = province;}

    inline const RegionField & GetCity() const {return m_city;}
    inline RegionField * GetMutableCity() {return &m_city;}
    inline void SetCity(const RegionField & city) {m_city = city;}

    inline wxString GetLangCodeName() const
    {
        return wxString::Format(wxT("%s_%s_%s"), m_country.GetName(REGION_CODE).c_str(),
            m_province.GetName(REGION_CODE).c_str(), m_city.GetName(REGION_CODE).c_str());
    }

    bool MatchName(const wxString & name) const;

private:
    RegionField m_country;
    RegionField m_province;
    RegionField m_city;
};

class RegionManager
{
public:
    bool Load(const wxString & fileName);
    vector<Region> GetRegions(const wxString & filter);

    int Save(const wxString & dir);

    RegionField * GetRegionById(int id);

    int UpdateField(int fieldId, int langId, const wxString & fieldName);

    int CreateField(Region * region);

    vector<const RegionField *> GetCountries();

    vector<const RegionField *> GetProvinces(int countryId);

    vector<const RegionField *> GetCities(int provinceId);

private:
    int SaveData(const wxString & fileName, int maxLangId = 1<<29);
    int SaveServer(const wxString & fileName);
    int SaveAndroid(const wxString & fileName);

private:
    map<int, RegionField> m_regionFields;
};

#endif // REGIONMANAGER_H_INCLUDED
